package com.zyw.configuration;

import com.zyw.security.shiro.stateless.StatelessDefaultSubjectFactory;
import com.zyw.security.shiro.stateless.filter.StatelessAuthcFilter;
import com.zyw.security.shiro.stateless.realm.StatelessRealm;
import com.zyw.utils.PropertyHolder;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.mgt.DefaultWebSubjectFactory;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.web.filter.DelegatingFilterProxy;

import javax.servlet.Filter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhangyw
 * @date 2017/12/18 14:40
 */
public class ShiroStatelessConfiguration {

    private SecurityManager securityManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
//        SimpleCookie simpleCookie = new SimpleCookie("token");
//        simpleCookie.setMaxAge(1800);
//        simpleCookie.setHttpOnly(true);

        // 关闭定时检查失效的session
        sessionManager.setSessionValidationSchedulerEnabled(false);
//        sessionManager.setSessionIdCookie(simpleCookie);

        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator sessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        // 关闭 session 存储策略
        sessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator);

        List<Realm> realms = new ArrayList<>();
        realms.add(new StatelessRealm());

        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setSessionManager(sessionManager);
        // 设置 subject 创建工厂，关闭session 创建
        securityManager.setSubjectFactory(new DefaultWebSubjectFactory());
        securityManager.setSubjectDAO(subjectDAO);
        securityManager.setRealms(realms);

        // 设置 securityUtils manager ，方便全局调用
        SecurityUtils.setSecurityManager(securityManager);
        return securityManager;
    }

    private Map<String, Filter> filters() {
        Map<String, Filter> filters = new LinkedHashMap<>();

        StatelessAuthcFilter authcFilter = new StatelessAuthcFilter();
        authcFilter.setName(authcFilter.getClass().getName());
        authcFilter.setPathConsolePattern(PropertyHolder.getString("path.console.prefix") + "/**");
        authcFilter.setPathRestPattern(PropertyHolder.getString("path.console.prefix") + "/**");

        filters.put("authc", authcFilter);
        return filters;
    }

    private ShiroFilterChainDefinition filterChainDefinition() {
        DefaultShiroFilterChainDefinition filterChainDefinition = new DefaultShiroFilterChainDefinition();
        filterChainDefinition.addPathDefinition(PropertyHolder.getString("path.console.prefix") + "/**", "authc");
        filterChainDefinition.addPathDefinition(PropertyHolder.getString("path.rest.prefix") + "/**", "authc");
        return filterChainDefinition;
    }


    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilterFactoryBean() throws Exception {
        ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
        filterFactoryBean.setSecurityManager(securityManager());
        filterFactoryBean.setFilterChainDefinitionMap(filterChainDefinition().getFilterChainMap());
        filterFactoryBean.setFilters(filters());
        filterFactoryBean.setLoginUrl(PropertyHolder.getString("shiro.loginUrl", "/auth/login"));
        filterFactoryBean.setSuccessUrl(PropertyHolder.getString("shiro.successUrl", "/index.html"));
        return filterFactoryBean;
    }

    /**
     * 代理 和 配置 webxml中的 filter
     *
     * @return FilterRegistrationBean
     */
//    @Bean
//    public FilterRegistrationBean filterRegistrationBean() {
//        FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
//        filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
//        //  该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理
//        filterRegistration.addInitParameter("targetFilterLifecycle", "true");
//        filterRegistration.setEnabled(true);
//        filterRegistration.addUrlPatterns(PropertyHolder.getArrayString("shiro.filterUrls"));// 可以自己灵活的定义很多，避免一些根本不需要被Shiro处理的请求被包含进来
//        return filterRegistration;
//    }

}
